<template>
  <div
    class="mint-range"
    :style="{ height: height + 'rem' }"
    :class="{ 'mint-range--disabled': disabled }"
  >
    <slot name="start"></slot>
    <div
      class="mint-range-content"
      ref="content"
      :style="{ 'margin-right': btnWidth + 'rem' }"
    >
      <div
        class="mint-range-runway"
        :style="{ height: height + 'rem', right: -btnWidth + 'rem' }"
      ></div>
      <div
        class="mint-range-progress"
        :style="{ width: progress + '%', height: height + 'rem' }"
      ></div>
      <div
        class="mint-range-thumb"
        ref="thumb"
        :style="{
          left: progress + '%',
          width: btnWidth + 'rem',
          height: btnHeight + 'rem',
          top: -(btnHeight - height) / 2 + 'rem',
        }"
        :class="{ 'thumb-round': btnRound }"
      ></div>
    </div>
    <slot name="end"></slot>
    <div
      class="mint-range-progress-real"
      :style="{ width: progress + '%', height: height + 'rem' }"
    ></div>
  </div>
</template>

<script type="text/babel">
import draggable from "./draggable";

export default {
  name: "mint-range",
  props: {
    min: {
      // 区间最小值
      type: Number,
      default: 0,
    },
    max: {
      type: Number,
      default: 100,
    },
    height: {
      // range高度
      type: Number,
      default: 0.1,
    },
    step: {
      // 滑动步数
      type: Number,
      default: 1,
    },
    disabled: {
      // 禁止滑动
      type: Boolean,
      default: false,
    },
    value: {
      // 预设值
      type: Number,
    },
    btnWidth: {
      // 滑块的宽
      type: Number,
      default: 0.3,
    },
    btnHeight: {
      // 滑块的高
      type: Number,
      default: 0.3,
    },
    btnRound: {
      // 滑块默认为圆形
      type: Boolean,
      default: true,
    },
  },
  computed: {
    progress() {
      const value = this.value;
      if (typeof value === "undefined" || value === null) return 0;
      return Math.floor(((value - this.min) / (this.max - this.min)) * 100);
    },
  },
  mounted() {
    const thumb = this.$refs.thumb;
    const content = this.$refs.content;
    const getThumbPosition = () => {
      const contentBox = content.getBoundingClientRect();
      const thumbBox = thumb.getBoundingClientRect();
      return {
        left: thumbBox.left - contentBox.left,
        top: thumbBox.top - contentBox.top,
        thumbBoxLeft: thumbBox.left,
      };
    };
    let dragState = {};
    draggable(thumb, {
      start: (event) => {
        if (this.disabled) return;
        const position = getThumbPosition();
        const thumbClickDetalX = event.clientX - position.thumbBoxLeft;
        dragState = {
          thumbStartLeft: position.left,
          thumbStartTop: position.top,
          thumbClickDetalX: thumbClickDetalX,
        };
      },
      drag: (event) => {
        if (this.disabled) return;
        const contentBox = content.getBoundingClientRect();
        const deltaX =
          event.pageX -
          contentBox.left -
          dragState.thumbStartLeft -
          dragState.thumbClickDetalX;
        const stepCount = Math.ceil((this.max - this.min) / this.step);
        const newPosition =
          dragState.thumbStartLeft +
          deltaX -
          ((dragState.thumbStartLeft + deltaX) %
            (contentBox.width / stepCount));
        let newProgress = newPosition / contentBox.width;
        if (newProgress < 0) {
          newProgress = 0;
        } else if (newProgress > 1) {
          newProgress = 1;
        }
        this.$emit(
          "input",
          Math.round(this.min + newProgress * (this.max - this.min))
        );
      },
      end: () => {
        if (this.disabled) return;
        this.$emit("change", this.value);
        dragState = {};
      },
    });
  },
};
</script>

<style>
.mint-range {
  width: 100%;
  position: relative;
  display: -webkit-box;
  display: -ms-flexbox;
  box-sizing: border-box;
}

.mint-range-content {
  position: relative;
  -webkit-box-flex: 1;
  -ms-flex: 1;
  flex: 1;
}

.mint-range-runway {
  position: absolute;
  top: 0;
  left: 0;
  background-color: #a9acb1;
}

.mint-range-progress,
.mint-range-progress-real {
  position: absolute;
  display: block;
  background-color: #26a2ff;
  top: 0;
  width: 0;
}

.mint-range-progress {
  opacity: 0;
}

.mint-range-thumb {
  background-color: #a9ccf2;
  position: absolute;
  left: 0;
  cursor: move;
  z-index: 2;
}

.thumb-round {
  border-radius: 100%;
  box-shadow: 0 1px 0.03rem rgba(0, 0, 0, 0.4);
}

.mt-range--disabled {
  opacity: 0.5;
}
</style>
